﻿using ImageManager.Common;
using ImageManager.ImageService;
using ImageManager.Model;
using ImageManager.MyExcep;
using Microsoft.AspNetCore.Authorization;
using System.Net;

namespace ImageManager.ImageApi.AuthenticationInjection
{
    public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationRequirement>
    {
        IHttpContextAccessor httpContextAccessor;
        IMyFailureReason reason;
        public MyAuthorizationHandler(IHttpContextAccessor httpContextAccessor, IMyFailureReason reason)
        {
            this.httpContextAccessor = httpContextAccessor;
            this.reason = reason;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyAuthorizationRequirement requirement)
        {
            var defHttpContext = context.Resource as DefaultHttpContext;
            if (defHttpContext == null || defHttpContext.GetEndpoint() == null)
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
            var clientIp = defHttpContext.Connection.RemoteIpAddress.ToString();
            var endpoint = defHttpContext.GetEndpoint();
            var ulAtt = endpoint.Metadata.FirstOrDefault(filter => filter is MyAuthorizeAttribute) as MyAuthorizeAttribute;
            if (ulAtt == null)
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
            MyLogger.Auth($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问需要进行身份认证");
            try
            {
                var onlineInfo = ServiceLoader.GetService<OnlineUser>();
                var userSP = ServiceLoader.GetService<UserServiceProvider>();
                TokenManager.SetupUser(onlineInfo);
                userSP.SetupOnLineUser(onlineInfo);
                if (ulAtt.AuthorizeLevel == AuthorizeLevelEnum.RootOnly && !onlineInfo.IsRoot)
                {
                    MyLogger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问的身份级别认证失败");
                    reason.Init($"模块{endpoint.DisplayName}需要权限为根用户", HttpStatusCode.Forbidden);
                    context.Fail();
                }
                else if (ulAtt.AuthorizeLevel == AuthorizeLevelEnum.ACL && !onlineInfo.IsRoot )
                {
                    var mod = SystemVar.ModuleList.FirstOrDefault(r => r.AccessMode == MyModAccessMode.ACL && r.ModCode == ulAtt.Module);
                    if (mod == null)
                        throw new MyException($"使用了一个不存在或不支持权限表的模块{ulAtt.Module}进行权限表鉴权操作");
                    var usrGroupDetail = onlineInfo.Detail;
                    if (usrGroupDetail.Where(r => r.Mod == mod.Pk).Any(d =>
                    (ulAtt.ModPermission == ModPermissionEnum.Approved && d.Approve
                        || ulAtt.ModPermission == ModPermissionEnum.Write && d.Write
                        || ulAtt.ModPermission == ModPermissionEnum.Read && d.Read
                        || ulAtt.ModPermission == ModPermissionEnum.Remove && d.Remove)
                    ))
                    {
                        context.Succeed(requirement);
                        return Task.CompletedTask;
                    }
                    MyLogger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问的身份级别认证失败");
                    reason.Init($"模块{endpoint.DisplayName}需要权限表{mod.ModName},用户{onlineInfo.UserName}没有此权限", HttpStatusCode.Forbidden);
                    context.Fail();
                }
                else if (ulAtt.AuthorizeLevel == AuthorizeLevelEnum.AllUser)
                {
                    context.Succeed(requirement);
                    return Task.CompletedTask;
                }
                else
                {
                    context.Succeed(requirement);
                    return Task.CompletedTask;
                }
                return Task.CompletedTask;
            }
            catch (MyAuthorizationException ex)
            {
                reason.Init(ex.Message, HttpStatusCode.Unauthorized, ex.Message);
                context.Fail();
                MyLogger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问未被认证:{ExceptionUtil.FormatExceptionInfo(ex)}");
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                reason.Init(ex.Message, HttpStatusCode.InternalServerError);
                context.Fail();
                MyLogger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问未被认证:{ExceptionUtil.FormatExceptionInfo(ex)}");
                return Task.CompletedTask;
            }
        }
    }
}
